home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Libraries / BlobMgr / Blob Manager Demo 4 / DemoToh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-02-17  |  5.1 KB  |  241 lines  |  [TEXT/MACA]

  1. /*
  2.     Blob Manager Demonstration:  Tower of Hanoi
  3.  
  4.     26 July 1986    Paul DuBois
  5. */
  6.  
  7. # include    "BlobDemo.h"
  8.  
  9.  
  10. # define    xBase        17    /* upper left corner of apparatus base */
  11. # define    yBase        130
  12. # define    baseHeight    12    /* length is computed */
  13. # define    slotHeight    18    /* size of disk slots */
  14. # define    slotWidth    100
  15. # define    slotHGap    20    /* horiz. gap between slots    */
  16. # define    slotVGap    0    /* vert. gap between slots */
  17. # define    hExtra        20    /* extra space at ends of base */
  18. # define    nDisks        6    /* number of disks */
  19. # define    postWidth    12    /* height is computed */
  20.     
  21.  
  22. static GrafPtr            tohPort;
  23. static BlobSetHandle    donors;
  24. static BlobSetHandle    receptors;
  25. static BlobHandle        tower[3][nDisks];    /* induced data structure */
  26.  
  27.  
  28.  
  29. static DrawApparatus ()
  30. {
  31. int    postHeight, baseWidth, h, v, i;
  32. Rect    r;
  33.  
  34.     postHeight = nDisks * (slotHeight + slotVGap) + postWidth/2;
  35.     h = xBase + hExtra + slotWidth/2 - postWidth/2;
  36.     SetRect (&r, h, yBase - postHeight, h + postWidth, yBase+postWidth/2);
  37.  
  38.     for (i = 0; i < 3; ++i)
  39.     {
  40.         FillRoundRect (&r, postWidth, postWidth, gray);
  41.         FrameRoundRect (&r, postWidth, postWidth);
  42.         OffsetRect (&r, slotWidth + slotHGap, 0);
  43.     }
  44.  
  45.     baseWidth = 3 * slotWidth + 2 * slotHGap + 2 * hExtra;
  46.     SetRect (&r, xBase, yBase, xBase + baseWidth, yBase + baseHeight);
  47.     FillRect (&r, dkGray);
  48.     FrameRect (&r);
  49. }
  50.  
  51.  
  52. /*
  53.     If a disk was moved onto a pile, but has empty slots under it,
  54.     drop it until it can't go any farther.
  55. */
  56.  
  57. static DropDisk ()
  58. {
  59. register int    i, j;
  60.  
  61.     for (i = 0; i < 3; ++i)
  62.     {
  63.         for (j = nDisks - 1; j > 0; --j)    /* don't check bottom pos */
  64.         {
  65.             if (BGlob (tower[i][j]) != nil)
  66.             {
  67.                 if (BGlob (tower[i][j-1]) == nil)
  68.                     TransferGlob (tower[i][j], tower[i][j-1]);
  69.             }
  70.         }
  71.     }
  72. }
  73.  
  74.  
  75. static Mouse (pt, t, mods)
  76. Point    pt;
  77. long    t;
  78. int        mods;
  79. {
  80.  
  81.     BlobClick (pt, t, nil, receptors);
  82.     DropDisk ();
  83. }
  84.  
  85.  
  86. /*
  87.     The advisory functions as follows:  receptor clicks are checked
  88.     and if the click isn't in the top disk of a pile, the click is
  89.     ignored (message advRClick).  When a receptor is dragged somewhere
  90.     else, it must be to a pile in which the disk under it is larger -
  91.     can't drag onto a smaller disk (message advXfer).
  92. */
  93.  
  94. static Boolean Advisory (mesg, b)
  95. int            mesg;
  96. BlobHandle    b;
  97. {
  98. BlobHandle    g;
  99. int            index, pile, piece, i;
  100. static int    srcRank;
  101.  
  102.     index = GetBlobIndex (b, receptors);
  103.     pile = index / nDisks;        /* 0 .. 2 */
  104.     piece = index % nDisks;        /* 0 .. nDisks-1 */
  105.     
  106.     switch (mesg)
  107.     {
  108.         case advRClick:
  109.         {
  110.             if (piece < nDisks - 1 && BGlob (NextBlob (b)) != nil)
  111.                 return (false);
  112.             srcRank = GetBRefCon (BGlob (b));    /* rank of dragged piece */
  113.             break;
  114.         }
  115.         case advXfer:
  116.         {
  117.             for (i = 0; i < piece; ++i)
  118.             {
  119.                 if ((g = BGlob (tower[pile][i])) != nil)
  120.                 {
  121.                     if (GetBRefCon (g) > srcRank)
  122.                         return (false);
  123.                 }
  124.             }
  125.             break;
  126.         }
  127.     }
  128.     return (true);
  129. }
  130.  
  131.  
  132. static Update (resized)
  133. Boolean    resized;
  134. {
  135.     DrawControls (tohPort);
  136.     DrawApparatus ();
  137.     DrawBlobSet (receptors);
  138. }
  139.  
  140.  
  141. static Activate (active)
  142. Boolean    active;
  143. {
  144.     if (active)
  145.     {
  146.         SetDragRects (tohPort);
  147.         SetBCPermissions (false, true, false, false, false);
  148.         SetBCAdvisory (Advisory);
  149.     }
  150.     else
  151.         SetBCAdvisory (nil);
  152. }
  153.  
  154. /*
  155.     Call this before static MakeDonors
  156. */
  157.  
  158. static MakeReceptors ()
  159. {
  160. int            i, j, h, v;
  161. BlobHandle    b;
  162. Rect        r, r2, r3;
  163.  
  164.     receptors = NewBlobSet ();
  165.     for (i = 0; i < 3; ++i)
  166.     {
  167.         for (j = 0; j < nDisks; ++j)
  168.         {
  169.             b = NewBlob (receptors, false, 0, false, 0L);
  170.             tower[i][j] = b;
  171.             OpenBlob ();
  172.             SetRect (&r, 0, 0, slotWidth, slotHeight);
  173.             h = slotWidth/2 - postWidth/2;
  174.             SetRect (&r2, h, -1, h + postWidth, slotHeight+1);
  175.             FillRect (&r2, gray);    /* fill in post area */
  176.             SetRect (&r3, 0, 0, h, slotHeight);    /* erase on sides of post */
  177.             EraseRect (&r3);
  178.             SetRect (&r3, h + postWidth, 0, slotWidth, slotHeight);
  179.             EraseRect (&r3);
  180.             FrameRect (&r2);
  181.             r2 = r;
  182.             InsetRect (&r2, 0, 1);
  183.             CloseRectBlob (b, &r2, &r);
  184.             h = xBase + hExtra + i * (slotWidth + slotHGap);
  185.             v = yBase - (j+1) * (slotHeight + slotVGap);
  186.             MoveBlob (b, inFullBlob, h, v);
  187.         }
  188.     }
  189. }
  190.  
  191.  
  192. /*
  193.     Make donors.  These are the pieces that get moved.  They're always
  194.     attached to some receptor, and just float from one receptor to
  195.     another.  The rank of each piece is stored in the reference constant
  196.     field.  The bottom piece is 0, the top is nDisks-1.
  197. */
  198.  
  199. static MakeDonors ()
  200. {
  201. int            i, j;
  202. BlobHandle    b;
  203. Rect        r, r2;
  204.  
  205.     donors = NewBlobSet ();
  206.     for (i = 0; i < nDisks; ++i)
  207.     {
  208.         b = NewBlob (donors, false, 1, false,
  209.                                     (long) i);    /* refCon is disk rank */
  210.         OpenBlob ();
  211.         SetRect (&r, 0, 0, slotWidth, slotHeight);
  212.         j = 20 + (nDisks-i-1) * 4;
  213.         SetRect (&r2, slotWidth/2 - j, 1, slotWidth/2 + j, slotHeight-1);
  214.         EraseRect (&r);
  215.         FrameRoundRect (&r2, slotHeight, slotHeight);
  216.         CloseRectBlob (b, &r, &r);
  217.         GlueGlob (b, tower[0][i]);    /* glue to first column */
  218.     }
  219.  
  220. }
  221.  
  222.  
  223. TohInit ()
  224. {
  225.     SkelWindow (tohPort = GetDemoWind (tohWindRes),
  226.                 Mouse,            /* mouse clicks */
  227.                 nil,            /* key clicks */
  228.                 Update,            /* updates */
  229.                 Activate,        /* activate/deactivate events */
  230.                 nil,            /* close window */
  231.                 DoWClobber,        /* dispose of window */
  232.                 nil,            /* idle proc */
  233.                 false);            /* irrelevant, since no idle proc */
  234.                 
  235.     MakeReceptors ();
  236.     MakeDonors ();
  237.     EnableBlobSet (receptors);
  238.     Update ();
  239.     ValidRect (&tohPort->portRect);
  240. }
  241.